package com.atguigu.gmall.cart.service.impl;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.consts.RedisConst;
import com.atguigu.gmall.common.util.AuthUtil;
import com.atguigu.gmall.common.util.JSONStr;
import com.atguigu.gmall.feign.product.ProductFeignClient;
import com.atguigu.gmall.model.cart.CartItem;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.model.to.UserAuthTo;
import com.fasterxml.jackson.core.type.TypeReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

/**
 * @Author 卡尼奶
 * @Date 2022/6/1 20:20
 * @Version 1.0
 */
@Service
public class CartServiceImpl implements CartService {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ProductFeignClient productFeignClient;

    @Override
    public CartItem addToCart(Long skuId, Integer skuNum) {
        String cartRedisKey = getCartRedisKey();
        //保存商品到redis中
        CartItem cartItem = saveRedis(skuId, skuNum, cartRedisKey);
        return cartItem;
    }

    private CartItem saveRedis(Long skuId, Integer skuNum, String cartRedisKey) {
        BoundHashOperations<String, String, String> boundHashOps = redisTemplate.boundHashOps(cartRedisKey);
        //1、判断redis中是否存在这个商品
        Boolean flag = boundHashOps.hasKey(skuId.toString());
        if (!flag) {
            //2、如果不存在，新增
            //根据商品ID获取sku信息
            SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId).getData();
            //把SkuInfo对象封装成CartItem对象
            CartItem cartItem = objToCartItem(skuInfo);
            cartItem.setSkuNum(skuNum);
            String jsonStr = JSONStr.toJsonStr(cartItem);
            //保存到redis中
            boundHashOps.put(skuId.toString(), jsonStr);
            return cartItem;
        } else {
            //3、如果存在，则修改商品数量
            String json = boundHashOps.get(skuId.toString());
            CartItem cartItem = JSONStr.strToObj(json, new TypeReference<CartItem>() {
            });
            cartItem.setSkuNum(cartItem.getSkuNum() + skuNum);
            boundHashOps.put(skuId.toString(), JSONStr.toJsonStr(cartItem));
            return cartItem;
        }
    }

    private CartItem objToCartItem(SkuInfo skuInfo) {
        CartItem cartItem = new CartItem();
        cartItem.setId(skuInfo.getId());
        UserAuthTo userAuth = AuthUtil.getUserAuth();
        if (userAuth.getUserId() != null) {
            cartItem.setUserId(userAuth.getUserId().toString());
        } else {
            cartItem.setUserId(userAuth.getUserTempId());
        }
        cartItem.setSkuId(skuInfo.getId());
        cartItem.setCartPrice(skuInfo.getPrice());
        cartItem.setSkuDefaultImg(skuInfo.getSkuDefaultImg());
        cartItem.setSkuName(skuInfo.getSkuName());
        cartItem.setIsChecked(1);
        cartItem.setCreateTime(new Date());
        cartItem.setUpdateTime(new Date());
        cartItem.setSkuPrice(skuInfo.getPrice());

        return cartItem;
    }

    /**
     * 获取购物车用户操作的key
     *
     * @return
     */
    @Override
    public String getCartRedisKey() {
        String key = RedisConst.USER_CART_PREFIX;
        //从feign中获取用户Id和临时Id
        UserAuthTo userAuth = AuthUtil.getUserAuth();
        if (userAuth.getUserId() != null) {
            //已登录
            return key + userAuth.getUserId();
        }
        //未登录
        return key + userAuth.getUserTempId();
    }

    @Override
    public List<CartItem> getCartList() {
        String cartRedisKey = getCartRedisKey();
        BoundHashOperations<String, String, String> boundHashOps = redisTemplate.boundHashOps(cartRedisKey);
        //从redis中获取所有商品JSON数据
        List<String> values = boundHashOps.values();
        List<CartItem> collect = values.stream().map((v) -> {
                    CartItem cartItem = JSONStr.strToObj(v, new TypeReference<CartItem>() {
                    });
                    return cartItem;
                }).sorted((o1, o2) -> {
                    return o2.getUpdateTime().compareTo(o1.getUpdateTime());
                })
                .collect(Collectors.toList());
//        List<CartItem> list = new ArrayList<>();
//        for (String value : values) {
//            CartItem cartItem = JSONStr.strToObj(value, new TypeReference<CartItem>() {
//            });
//            list.add(cartItem);
//        }
        return collect;
    }
}
